﻿// FormlyNET module...

(function () {
    "use strict";

    angular.module("FormlyNET", ['ui.bootstrap', 'ui.mask', 'ui.bootstrap.datetimepicker', 'ui.select',
                                 'ngSanitize', 'naif.base64',
                                 'GrayParrot.AngularJS.Directives.DateTimePicker',
                                 'GrayParrot.AngularJS.Directives.FileUpload']);

    var app = angular.module("FormlyNET");

    app.factory('FieldsService', function ($http) {
        return {
            getFields: getFields
        };

        function getFields(url) {
            ////return $http.post(url, { headers: { 'Cache-Control': 'no-cache' } });
            //return $http.get(url, { headers: { 'Cache-Control': 'no-cache' } });

            return $http(url);
        }
    });

    //app.directive('ngLocal', ['$filter', function ($filter) {
    //    return {
    //        require: 'ngModel',
    //        priority: 1,
    //        link: function ($scope, $element, $attrs, ngModelCtrl) {
    //            ngModelCtrl.$parsers.push(function (viewValue) {

    //                var d = new Date(viewValue);
    //                var day = d.getDay();

    //                var newDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 2, 0, 0, 0);

    //                viewValue = newDate;

    //                //viewValue = $filter('date')(viewValue, 'dd/MM/yyyy');

    //                //viewValue = moment.utc(viewValue).format("YYYY-MM-DDTHH:mm:ssZZ")

    //                return viewValue;
    //            });
    //            ngModelCtrl.$render = function () {
    //                var val = $filter('date')(ngModelCtrl.$viewValue, 'dd/MM/yyyy');
    //                $element.val(val);
    //            };
    //        }
    //    };
    //}]);

    app.directive('ngLocal', ['$parse', function ($parse) {
        var directive = {
            restrict: 'A',
            require: ['ngModel'],
            link: link
        };
        return directive;

        function link(scope, element, attr, ctrls) {
            var ngModelController = ctrls[0];

            // called with a JavaScript Date object when picked from the datepicker
            ngModelController.$parsers.push(function (viewValue) {
                // undo the timezone adjustment we did during the formatting
                viewValue.setMinutes(viewValue.getMinutes() - viewValue.getTimezoneOffset());

                // sets seconds (and milliseconds) to 00
                viewValue.setSeconds(0);
                viewValue.setMilliseconds(0);

                // we just want a local date in ISO format
                return viewValue; //.toISOString().substring(0, 10);
            });

            // called with a 'yyyy-mm-dd' string to format
            ngModelController.$formatters.push(function (modelValue) {
                if (!modelValue) {
                    return undefined;
                }
                // date constructor will apply timezone deviations from UTC (i.e. if locale is behind UTC 'dt' will be one day behind)
                var dt = new Date(modelValue);
                // 'undo' the timezone offset again (so we end up on the original date again)
                dt.setMinutes(dt.getMinutes() + dt.getTimezoneOffset());
                dt.setSeconds(0);
                dt.setMilliseconds(0);
                return dt;
            });
        }
    }]);

    app.provider('CustomTypes',
        function ProvideCustomTypes() {

            var m_container = 'body';  // html body is the default container...

            /* datepicker */
            var attributes = [
                'date-disabled',
                'custom-class',
                'show-weeks',
                'starting-day',
                'init-date',
                'min-mode',
                'max-mode',
                'format-day',
                'format-month',
                'format-year',
                'format-day-header',
                'format-day-title',
                'format-month-title',
                'year-range',
                'shortcut-propagation',
                'datepicker-popup',
                'show-button-bar',
                'current-text',
                'clear-text',
                'close-text',
                'close-on-date-selection',
                'datepicker-append-to-body'
            ];

            var bindings = [
              'datepicker-mode',
              'min-date',
              'max-date'
            ];

            var ngModelAttrs = {};

            angular.forEach(attributes, function (attr) {
                ngModelAttrs[camelize(attr)] = { attribute: attr };
            });

            angular.forEach(bindings, function (binding) {
                ngModelAttrs[camelize(binding)] = { bound: binding };
            });
            /* datepicker */

            /*timerpicker*/
            var ngModelAttrsTP = {};

            // attributes
            angular.forEach([
              'meridians',
              'readonly-input',
              'mousewheel',
              'arrowkeys'
            ], function (attr) {
                ngModelAttrsTP[camelize(attr)] = { attribute: attr };
            });

            // bindings
            angular.forEach([
              'hour-step',
              'minute-step',
              'show-meridian'
            ], function (binding) {
                ngModelAttrsTP[camelize(binding)] = { bound: binding };
            });
            /*timepicker*/

            /*datetimerpicker*/
            var ngModelAttrsDTP = {};

            // attributes
            angular.forEach([
              'min-view',
              'start-view',
              'minute-step',
              'dropdown-selector'
            ], function (attr) {
                ngModelAttrsDTP[camelize(attr)] = { attribute: attr };
            });
            /*datetimerpicker*/

            var inputFile = {
                name: 'upload',
                extends: 'input',
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                link: function (scope, el, attrs) {
                    el.on("change", function (changeEvent) {
                        var file = changeEvent.target.files[0];
                        if (file) {
                            console.log('scope.id', scope.id);
                            var fd = new FormData();
                            // use key on backEnd
                            fd.append('uploadFile', file);
                            scope.$emit('fileToUpload', fd);
                            var fileProp = {};
                            for (var properties in file) {
                                if (!angular.isFunction(file[properties])) {
                                    fileProp[properties] = file[properties];
                                }
                            }
                            scope.fc.$setViewValue(fileProp);
                        } else {
                            scope.fc.$setViewValue(undefined);
                        }
                    });
                    //el.on("focusout", function (focusoutEvent) {
                    //    // dont run validation , user still opening pop up file dialog
                    //    if ($window.document.activeElement.id === scope.id) {
                    //        // so we set it untouched
                    //        scope.$apply(function (scope) {
                    //            scope.fc.$setUntouched();
                    //        });
                    //    } else {
                    //        // element losing focus so we trigger validation
                    //        scope.fc.$validate();
                    //    }
                    //});

                },
                defaultOptions: {
                    templateOptions: {
                        type: 'file',
                        required: true
                    }
                }
            };

            var grayParrotFileUploadObj = {
                name: 'grayParrotFileUpload',
                template: '<input file-upload type="text" ng-model="model[options.key]" />',
                //templateUrl: 'gp-dateTimePicker.html',
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                defaultOptions: {
                    ngModelAttrs: ngModelAttrs,
                    templateOptions: {
                    }
                }
            };

            var grayParrotDateTimeObj = {
                name: 'grayParrotDateTimePicker',
                //template: '<dalot type="text" ng-model="user.dateOfBirth" />',
                templateUrl: 'gp-dateTimePicker.html',
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                defaultOptions: {
                    ngModelAttrs: ngModelAttrs,
                    templateOptions: {
                        format: 'dd MM yyyy - HH:ii p',
                        initDate: new Date(),
                        showMeridian: false,
                        autoclose: true,
                        todayBtn: true,
                        todayHighlight: false,
                        language: 'it',
                        minView: 2, startView: 2,
                        defaultValue: new Date()
                    }
                }
            };

            var datetimeObj = {
                name: 'dateTimePicker',
                templateUrl: function (ngModelAttrsDTP) {
                    if (ngModelAttrsDTP.templateOptions.dataDatetimepickerConfig.dropdownSelector != '') {
                        return 'dateTimePickerDropDown.html';
                    } else {
                        return 'dateTimePicker.html';
                    }
                },
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                defaultOptions: {
                    ngModelAttrs: ngModelAttrsDTP,
                    templateOptions: {
                        dataDatetimepickerConfig: {
                            startView: 'day',
                            minView: 'minute',
                            minuteStep: 5,
                            dropdownSelector: null
                        }
                    }
                }
            };

            var maskObj = {
                name: 'maskedInput',
                extends: 'input',
                template: '<input class="form-control" ng-model="model[options.key]" />',
                defaultOptions: {
                    ngModelAttrs: {
                        mask: {
                            attribute: 'ui-mask'
                        },
                        maskPlaceholder: {
                            attribute: 'ui-mask-placeholder'
                        }
                    },
                    templateOptions: {
                        maskPlaceholder: ''
                    }
                }
            };

            var timeObj = {
                name: 'timepicker',
                template: '<timepicker ng-Local ng-model="model[options.key]"></timepicker>',
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                defaultOptions: {
                    ngModelAttrs: ngModelAttrsTP,
                    templateOptions: {
                        datepickerOptions: {}
                    }
                }
            };

            var dateObj = {
                name: 'datepicker',
                templateUrl: 'datepicker.html',
                wrapper: ['bootstrapLabel', 'bootstrapHasError'],
                defaultOptions: {
                    ngModelAttrs: ngModelAttrs,
                    templateOptions: {
                        datepickerOptions: {
                            format: 'dd/MM/yyyy',
                            initDate: new Date()
                        }
                    }
                },
                controller: ['$scope', function ($scope) {
                    $scope.datepicker = {};

                    $scope.datepicker.opened = false;

                    $scope.datepicker.open = function ($event) {
                        $scope.datepicker.opened = true;
                    };
                }]
            };

            var inputNumberObj = {
                name: 'inputnumber',
                extends: 'input',
                defaultOptions: {
                    ngModelAttrs: {
                        step: {
                            attribute: 'step'
                        },
                        value: {
                            attribute: 'value'
                        }
                    }
                }
            };

            var asyncUISelect2Obj = {
                name: 'ui-select-single-search',
                extends: 'select',
                templateUrl: 'uiSelectAsyncSearch.html',
                controller: function ($http, $scope) {
                    var url = $scope.to.callback;

                    var dependsBy = $scope.to.dependsBy;
                    if (dependsBy === undefined) {

                        if (($scope.model !== undefined) && (!jQuery.isEmptyObject($scope.model))) {

                            //$scope.fields[$scope.index].
                            var m_prop = $scope.fields[$scope.index].templateOptions.editProp;
                            var m_value = $scope.model[$scope.fields[$scope.index].templateOptions.editProp];

                            $scope.to.loading = $http.post(url, { name: m_value }).
                                then(function (response) {
                                    $scope.to.options = response.data;

                                    return response;
                                }, function (response) {
                                    alert(response.status + ': ' + response.statusText);

                                    return response;
                                });

                        } else {

                            $scope.to.loading = $http.post(url, { name: '' }).
                                then(function (response) {
                                    $scope.to.options = response.data;

                                    return response;
                                }, function (response) {
                                    alert(response.status + ': ' + response.statusText);

                                    return response;
                                });

                        }
                    } else {
                        // depends by the value of item whose id is in dependsBy options...
                        //var itemBy = angular.element(dependsBy);
                        //alert(itemBy);

                        if (($scope.to.addonRight !== undefined) || ($scope.to.addonLeft !== undefined)) {
                            if ((($scope.to.addonRight !== undefined) && ($scope.to.addonRight.onClick !== undefined)) ||
                                (($scope.to.addonLeft !== undefined) && ($scope.to.addonLeft.onClick !== undefined))) {

                                var parameters = [];
                                if (dependsBy.indexOf(',') != -1) {
                                    var items = dependsBy.split(',');
                                    angular.forEach(items, function (value, key) {
                                        var item = 'model.' + value.trim();
                                        this.push(item);
                                    }, parameters);
                                } else {
                                    var item = 'model.' + dependsBy;
                                    parameters.push(item);
                                }

                                $scope.$watchGroup(parameters, function (newValues, oldValues, scope) {
                                    if (newValues != oldValues) {

                                        if ($scope.to.addonRight !== undefined) {
                                            $scope.to.addonRight.onClick = function () {

                                                var goOn = true;
                                                angular.forEach(newValues, function (value, key) {
                                                    if (value === undefined) {
                                                        goOn = false;
                                                        return goOn;
                                                    }
                                                });

                                                if (goOn) {
                                                    $scope.to.loading = $http.post(url, {
                                                        parameters: newValues
                                                    }).
                                                        then(function (response) {
                                                            $scope.to.options = response.data;

                                                            return response;
                                                        }, function (response) {
                                                            alert(response.status + ': ' + response.statusText);

                                                            return response;
                                                        });
                                                } else {
                                                    alert('Numero di parametri non corretto !');
                                                }
                                            }
                                        }

                                        if ($scope.to.addonLeft !== undefined) {
                                            $scope.to.addonRight.onClick = function () {
                                                var goOn = true;
                                                angular.forEach(newValues, function (value, key) {
                                                    if (value === undefined) {
                                                        goOn = false;
                                                        return goOn;
                                                    }
                                                });

                                                if (goOn) {

                                                    $scope.to.loading = $http.post(url, {
                                                        parameters: newValues
                                                    }).
                                                        then(function (response) {
                                                            $scope.to.options = response.data;

                                                            return response;
                                                        }, function (response) {
                                                            alert(response.status + ': ' + response.statusText);

                                                            return response;
                                                        });
                                                } else {
                                                    alert('Numero di parametri non corretto !');
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        } else {

                            if (dependsBy.indexOf(',') != -1) {
                                //var segments = str.split(',');
                                alert('ATTENZIONE: Sono stati indicati molteplici valori per la clausola "DependsBy" ma non viene utilizzato l\'AddOn in formato Pulsante !');
                            } else {
                                /* il controllo select dipende da un altro controllo di tipo select... */
                                var itemBy = 'model.' + dependsBy;

                                $scope.$watch(itemBy, function (newValue, oldValue, theScope) {
                                    if (newValue !== oldValue) {
                                        // logic to reload this select's options asynchronusly based on state's value (newValue)
                                        //console.log('new value is different from old value');
                                        if ($scope.model[$scope.options.key] && oldValue) {
                                            // reset this select
                                            $scope.model[$scope.options.key] = '';
                                        }
                                        // Reload options  angular.toJson(newValue, true)
                                        var param = newValue;
                                        $scope.to.loading = $http.post(url, { parameter: newValue }).
                                            then(function (response) {
                                                $scope.to.options = response.data;

                                                return response;
                                            }, function (response) {
                                                alert(response.status + ': ' + response.statusText);

                                                return response;
                                            });
                                    } else {

                                        if ($scope.to.forceLoad) {

                                            if ((oldValue != undefined) && (oldValue != '')) {
                                                $scope.to.loading = $http.post(url, { parameter: oldValue }).
                                                    then(function (response) {
                                                        $scope.to.options = response.data;

                                                        return response;
                                                    }, function (response) {
                                                        alert(response.status + ': ' + response.statusText);

                                                        return response;
                                                    });
                                            }
                                        }

                                    }
                                }, true);
                            }
                        }
                    }
                }
            };

            var asyncSelectObj = {
                name: 'asyncselect',
                //wrapper: 'loading',
                extends: 'select',
                controller: function ($http, $scope) {
                    var url = $scope.to.callback;

                    var dependsBy = $scope.to.dependsBy;
                    if (dependsBy === undefined) {

                        $scope.to.loading = $http.get(url).
                            then(function (response) {
                                $scope.to.options = response.data;

                                return response;
                            }, function (response) {
                                alert(response.status + ': ' + response.statusText);

                                return response;
                            });

                    } else {

                        var parameters = [];
                        if (dependsBy.indexOf(',') != -1) {
                            var items = dependsBy.split(',');
                            angular.forEach(items, function (value, key) {
                                var item = 'model.' + value.trim();
                                this.push(item);
                            }, parameters);
                        } else {
                            var item = 'model.' + dependsBy;
                            parameters.push(item);
                        }

                        $scope.$watchGroup(parameters, function (newValues, oldValues, scope) {
                            if (newValues != oldValues) {

                                var goOn = true;
                                goOn = CheckArrayValues(newValues);
                                //angular.forEach(newValues, function (value, key) {
                                //    if (value === undefined) {
                                //        goOn = false;
                                //        return goOn;
                                //    }
                                //});

                                if (goOn) {
                                    $scope.to.loading = $http.post(url, {
                                        parameters: newValues
                                    }).
                                        then(function (response) {
                                            $scope.to.options = response.data;

                                            return response;
                                        }, function (response) {
                                            alert(response.status + ': ' + response.statusText);

                                            return response;
                                        });
                                } else {
                                    //alert('Numero di parametri non corretto !');
                                }
                            } else {
                                if ($scope.to.forceLoad) {

                                    var goOn = true;
                                    goOn = CheckArrayValues(oldValues);

                                    if (goOn) {
                                        if ((oldValues != undefined) && (oldValues != '')) {
                                            $scope.to.loading = $http.post(url, { parameters: oldValues }).
                                                then(function (response) {
                                                    $scope.to.options = response.data;

                                                    return response;
                                                }, function (response) {
                                                    alert(response.status + ': ' + response.statusText);

                                                    return response;
                                                });
                                        }
                                    }
                                }
                            }

                        }, true);

                    }
                }
                //controller: function ($http, $scope) {
                //    var url = $scope.to.callback;

                //    var dependsBy = $scope.to.dependsBy;
                //    if (dependsBy === undefined) {

                //        $scope.to.loading = $http.get(url).
                //            then(function (response) {
                //                $scope.to.options = response.data;

                //                return response;
                //            }, function (response) {
                //                alert(response.status + ': ' + response.statusText);

                //                return response;
                //            });

                //    } else {
                //        // depends by the value of item whose id is in dependsBy options...
                //        //var itemBy = angular.element(dependsBy);
                //        //alert(itemBy);

                //        if (($scope.to.addonRight !== undefined) || ($scope.to.addonLeft !== undefined)) {
                //            if ((($scope.to.addonRight !== undefined) && ($scope.to.addonRight.onClick !== undefined)) ||
                //                (($scope.to.addonLeft !== undefined) && ($scope.to.addonLeft.onClick !== undefined))) {

                //                var parameters = [];
                //                if (dependsBy.indexOf(',') != -1) {
                //                    var items = dependsBy.split(',');
                //                    angular.forEach(items, function (value, key) {
                //                        var item = 'model.' + value.trim();
                //                        this.push(item);
                //                    }, parameters);
                //                } else {
                //                    var item = 'model.' + dependsBy;
                //                    parameters.push(item);
                //                }

                //                $scope.$watchGroup(parameters, function (newValues, oldValues, scope) {
                //                    if (newValues != oldValues) {

                //                        if ($scope.to.addonRight !== undefined) {
                //                            $scope.to.addonRight.onClick = function () {

                //                                var goOn = true;
                //                                angular.forEach(newValues, function (value, key) {
                //                                    if (value === undefined) {
                //                                        goOn = false;
                //                                        return goOn;
                //                                    }
                //                                });

                //                                if (goOn) {
                //                                    $scope.to.loading = $http.post(url, {
                //                                        parameters: newValues
                //                                    }).
                //                                        then(function (response) {
                //                                            $scope.to.options = response.data;

                //                                            return response;
                //                                        }, function (response) {
                //                                            alert(response.status + ': ' + response.statusText);

                //                                            return response;
                //                                        });
                //                                } else {
                //                                    alert('Numero di parametri non corretto !');
                //                                }
                //                            }
                //                        }

                //                        if ($scope.to.addonLeft !== undefined) {
                //                            $scope.to.addonRight.onClick = function () {
                //                                var goOn = true;
                //                                angular.forEach(newValues, function (value, key) {
                //                                    if (value === undefined) {
                //                                        goOn = false;
                //                                        return goOn;
                //                                    }
                //                                });

                //                                if (goOn) {

                //                                    $scope.to.loading = $http.post(url, {
                //                                        parameters: newValues
                //                                    }).
                //                                        then(function (response) {
                //                                            $scope.to.options = response.data;

                //                                            return response;
                //                                        }, function (response) {
                //                                            alert(response.status + ': ' + response.statusText);

                //                                            return response;
                //                                        });
                //                                } else {
                //                                    alert('Numero di parametri non corretto !');
                //                                }
                //                            }
                //                        }
                //                    }
                //                });
                //            }
                //        } else {

                //            if (dependsBy.indexOf(',') != -1) {
                //                //var segments = str.split(',');
                //                alert('ATTENZIONE: Sono stati indicati molteplici valori per la clausola "DependsBy" ma non viene utilizzato l\'AddOn in formato Pulsante !');
                //            } else {
                //                /* il controllo select dipende da un altro controllo di tipo select... */
                //                var itemBy = 'model.' + dependsBy;

                //                $scope.$watch(itemBy, function (newValue, oldValue, theScope) {
                //                    if (newValue !== oldValue) {
                //                        // logic to reload this select's options asynchronusly based on state's value (newValue)
                //                        //console.log('new value is different from old value');
                //                        if ($scope.model[$scope.options.key] && oldValue) {
                //                            // reset this select
                //                            $scope.model[$scope.options.key] = '';
                //                        }
                //                        // Reload options  angular.toJson(newValue, true)
                //                        var param = newValue;
                //                        $scope.to.loading = $http.post(url, { parameter: newValue }).
                //                            then(function (response) {
                //                                $scope.to.options = response.data;

                //                                return response;
                //                            }, function (response) {
                //                                alert(response.status + ': ' + response.statusText);

                //                                return response;
                //                            });
                //                    } else {

                //                        if ($scope.to.forceLoad) {

                //                            if ((oldValue != undefined) && (oldValue != '')) {
                //                                $scope.to.loading = $http.post(url, { parameter: oldValue }).
                //                                    then(function (response) {
                //                                        $scope.to.options = response.data;

                //                                        return response;
                //                                    }, function (response) {
                //                                        alert(response.status + ': ' + response.statusText);

                //                                        return response;
                //                                    });
                //                            }
                //                        }

                //                    }
                //                }, true);
                //            }
                //        }
                //    }
                //}
            };

            var asyncMultiCheckBoxObj = {
                name: 'asyncMultiCheckBox',
                //wrapper: 'loading',
                extends: 'multiCheckbox',
                controller: function ($http, $scope) {
                    var url = $scope.to.callback;

                    var dependsBy = $scope.to.dependsBy;

                    if (dependsBy === undefined) {
                        $scope.to.loading = $http.get(url).
                            then(function (response) {
                                $scope.to.options = response.data;

                                return response;
                            }, function (response) {
                                alert(response.status + ': ' + response.statusText);

                                return response;
                            });
                    } else {
                        var parameters = [];
                        if (dependsBy.indexOf(',') != -1) {
                            var items = dependsBy.split(',');
                            angular.forEach(items, function (value, key) {
                                var item = 'model.' + value.trim();
                                this.push(item);
                            }, parameters);
                        } else {
                            var item = 'model.' + dependsBy;
                            parameters.push(item);
                        }

                        $scope.$watchGroup(parameters, function (newValues, oldValues, scope) {
                            if (newValues != oldValues) {

                                var goOn = true;
                                goOn = CheckArrayValues(newValues);
                                //angular.forEach(newValues, function (value, key) {
                                //    if (value === undefined) {
                                //        goOn = false;
                                //        return goOn;
                                //    }
                                //});

                                if (goOn) {
                                    $scope.to.loading = $http.post(url, {
                                        parameters: newValues
                                    }).
                                        then(function (response) {
                                            $scope.to.options = response.data;

                                            return response;
                                        }, function (response) {
                                            alert(response.status + ': ' + response.statusText);

                                            return response;
                                        });
                                } else {
                                    //alert('Numero di parametri non corretto !');
                                }
                            } else {
                                if ($scope.to.forceLoad) {

                                    var goOn = true;
                                    goOn = CheckArrayValues(oldValues);

                                    if (goOn) {
                                        if ((oldValues != undefined) && (oldValues != '')) {
                                            $scope.to.loading = $http.post(url, { parameters: oldValues }).
                                                then(function (response) {
                                                    $scope.to.options = response.data;

                                                    return response;
                                                }, function (response) {
                                                    alert(response.status + ': ' + response.statusText);

                                                    return response;
                                                });
                                        }
                                    }
                                }
                            }

                        }, true);
                    }
                }
            };

            var asyncRadioObj = {
                name: 'asyncRadio',
                //wrapper: 'loading',
                extends: 'radio',
                controller: function ($http, $scope) {
                    var url = $scope.to.callback;

                    $scope.to.loading = $http.get(url).
                        then(function (response) {
                            $scope.to.options = response.data;

                            return response;
                        }, function (response) {
                            alert(response.status + ': ' + response.statusText);

                            return response;
                        });
                }
            };

            var fileInput64Obj = {
                name: 'image',
                templateUrl: 'image-upload.html',
                defaultOptions: {
                    templateOptions: {
                        required: false,
                        onChange: function ($viewValue, $modelValue, scope) {
                            $viewValue.foldername = this.folder;
                        }
                    }
                },
            };

            var repeatsection = {
                name: 'repeatsection',
                templateUrl: 'repeatSection.html',
                controller: function ($scope) {
                    var unique = 1;
                    $scope.formOptions = { formState: $scope.formState };
                    $scope.addNew = addNew;

                    $scope.copyFields = copyFields;

                    function copyFields(fields) {
                        fields = angular.copy(fields);
                        addRandomIds(fields);
                        return fields;
                    }

                    function addNew() {
                        $scope.model[$scope.options.key] = $scope.model[$scope.options.key] || [];
                        var repeatsection = $scope.model[$scope.options.key];
                        var lastSection = repeatsection[repeatsection.length - 1];
                        var newsection = {};
                        if (lastSection) {
                            newsection = angular.copy(lastSection);
                        }
                        repeatsection.push(newsection);
                    }

                    function addRandomIds(fields) {
                        unique++;
                        angular.forEach(fields, function (field, index) {
                            if (field.fieldGroup) {
                                addRandomIds(field.fieldGroup);
                                return; // fieldGroups don't need an ID
                            }

                            if (field.templateOptions && field.templateOptions.fields) {
                                addRandomIds(field.templateOptions.fields);
                            }

                            field.id = field.id || (field.key + '_' + index + '_' + unique + getRandomInt(0, 9999));
                        });
                    }

                    function getRandomInt(min, max) {
                        return Math.floor(Math.random() * (max - min)) + min;
                    }
                }
            };

            // return the public api for the provider...
            return ({
                getTypes: getTypes,

                $get: instantiateProvider
            });

            function camelize(string) {
                string = string.replace(/[\-_\s]+(.)?/g, function (match, chr) {
                    return chr ? chr.toUpperCase() : '';
                });
                // Ensure 1st char is always lowercase
                return string.replace(/^([A-Z])/, function (match, chr) {
                    return chr ? chr.toLowerCase() : '';
                });
            }

            function addDateTimePickerTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"dateTimePicker.html\">" +
                               "  <datetimepicker ng-Local ng-model=\"model[options.key]\" data-datetimepicker-config=\"to.dataDatetimepickerConfig\"></datetimepicker>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function addDateTimePickerDropDownTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"dateTimePickerDropDown.html\">" +
                               "<div class=\"dropdown\">" +
                               "  <a class=\"dropdown-toggle\" id=\"dropdown_{{::id}}\" role=\"button\" data-toggle=\"dropdown\" data-target=\"#\" href=\"#\">" +
                               "    <input id=\"{{::id}}\" name=\"{{::id}}\" type=\"text\" ng-Local class=\"form-control\" data-ng-model=\"model[options.key]\">" +
                               "  </a>" +
                               "  <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">" +
                               "    <datetimepicker ng-Local data-ng-model=\"model[options.key]\" data-datetimepicker-config=\"to.dataDatetimepickerConfig\" />" +
                               "  </ul>" +
                               "</div>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function addRepeatSectionTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"repeatSection.html\">" +
                    "<div>" +
                    "  <span><b>{{to.label}}</b></span>" +
                    "  <div class=\"{{hideRepeat}}\">" +
                    "    <div class=\"repeatsection\" ng-repeat=\"element in model[options.key]\" ng-init=\"fields = copyFields(to.fields)\">" +
                    "      <formly-form fields=\"fields\" model=\"element\" form=\"form\"></formly-form>" +
                    "      <div style=\"margin-bottom:20px;\">" +
                    "        <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"model[options.key].splice($index, 1)\">" +
                    "          Remove" +
                    "        </button>" +
                    "      </div>" +
                    "      <hr>" +
                    "  </div>" +
                    "  <p class=\"AddNewButton\">" +
                    "    <button type=\"button\" class=\"btn btn-primary\" ng-click=\"addNew()\" >Add</button>" +
                    "    <button type=\"reset\" class=\"btn btn-primary\">Reset</button>" +
                    "  </p>" +
                    "</div>" +
                    "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);

                //$(template).insertBefore("script");
                ////$('body').append(template);
            }

            function addDatepickerTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"datepicker.html\">" +
                               "     <input  type=\"text\"" +
                               "        id=\"{{::id}}\"" +
                               "        name=\"{{::id}}\"" +
                               "        ng-model=\"model[options.key]\"" +
                               "        ng-Local" +
                               "        class=\"form-control\"" +
                               "        ng-click=\"datepicker.open($event)\"" +
                               "        datepicker-popup=\"{{to.datepickerOptions.format}}\"" +
                               "        is-open=\"datepicker.opened\"" +
                               "        datepicker-options=\"to.datepickerOptions\" " +
                               "         />" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function addSelectTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"loading.html\">" +
                               "   <div ng-if=\"to.loading.$$state.status === 0\" style=\"line-height:34px\">" +
                               "       Loading..." +
                               "   </div>" +
                               "   <div ng-if=\"to.loading.$$state.status !== 0\">" +
                               "      <formly-transclude></formly-transclude>" +
                               "   </div>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function addUISelect2Template() {
                var template = "<script type=\"text/ng-template\" id=\"uiSelectAsyncSearch.html\">" +
                               "   <ui-select data-ng-model=\"model[options.key]\" data-required=\"{{to.required}}\" data-disabled=\"{{to.disabled}}\" theme=\"bootstrap\">" +
                               "   <ui-select-match placeholder=\"{{to.placeholder}}\">{{$select.selected[to.labelProp]}}</ui-select-match>" +
                               "   <ui-select-choices data-repeat=\"{{to.ngOptions}}\" data-refresh=\"to.refresh($select.search, options)\" data-refresh-delay=\"{{to.refreshDelay}}\" minimum-input-length=\"{{to.minimumInputLength}}\">" +
                               "      <div ng-bind-html=\"option[to.labelProp] | highlight: $select.search\"></div>" +
                               "      {{to.info}}" +
                               //"      <div><small>{{option.Descrizione}}</small></div>" +
                               "   </ui-select-choices>" +
                               "</ui-select>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function addImg64UploadTemplate() {
                var template = "<script type=\"text/ng-template\" id=\"image-upload.html\">" +
                               "   <div class=\"input-group\">" +
                               "     <span class=\"input-group-btn\">" +
                               "       <span class=\"btn btn-primary btn-file\">Browse &hellip;" +
                               "                 <input type=\"file\" ng-model=\"model[options.key]\" name=\"files\" accept=\"image/*\" maxsize=\"5000\" base-sixty-four-input=\"base-sixty-four-input\"/>" +
                               "       </span>" +
                               "     </span>" +
                               "     <input type=\"text\" value=\"{{model.FotoProdotto.filename}}\" readonly=\"readonly\" class=\"form-control\"/>" +
                               "   </div>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            /* <dalot type="text" ng-model="user.dateOfBirth" /> */
            function addGPDateTimePicker() {
                var template = "<script type=\"text/ng-template\" id=\"gp-dateTimePicker.html\">" +
                               "   <div class=\"input-group date form_datetime\">" +
                               //"      <input size=\"16\" type=\"text\" value=\"\" > " +
                               "      <dalot class=\"form-control\" type=\"text\" options={{to}} data-ng-model=\"model[options.key]\" data-date=\"model[options.initDate]\" /> " +
                               "      <span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-remove\"></span></span> " +
                               "      <span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-calendar\"></span></span>" +
                               "   </div>" +
                               "</script>";

                var myEl = angular.element(document.querySelector(m_container));
                myEl.append(template);
            }

            function getTypes(container) {
                m_container = container;

                var customTypes = Array();
                customTypes.push(inputNumberObj);
                customTypes.push(repeatsection);
                customTypes.push(dateObj);
                customTypes.push(asyncSelectObj);
                customTypes.push(asyncMultiCheckBoxObj);
                customTypes.push(asyncRadioObj);
                customTypes.push(timeObj);
                customTypes.push(maskObj);
                customTypes.push(datetimeObj);
                customTypes.push(asyncUISelect2Obj);
                customTypes.push(fileInput64Obj);
                customTypes.push(inputFile);
                customTypes.push(grayParrotDateTimeObj);
                customTypes.push(grayParrotFileUploadObj);

                addRepeatSectionTemplate();
                addDatepickerTemplate();
                addSelectTemplate();
                addDateTimePickerDropDownTemplate();
                addDateTimePickerTemplate();
                addUISelect2Template();
                addImg64UploadTemplate();
                addGPDateTimePicker();

                return customTypes;
            }

            // factory method...
            function instantiateProvider() {
                return ({
                    addRepeatSectionTemplate: addRepeatSectionTemplate
                });

                function addRepeatSectionTemplate() {
                    var template = "<script type=\"text/ng-template\" id=\"repeatSection.html\">" +
                        "<div>" +
                        "  <span><b>{{to.label}}</b></span>" +
                        "  <div class=\"{{hideRepeat}}\">" +
                        "    <div class=\"repeatsection\" ng-repeat=\"element in model[options.key]\" ng-init=\"fields = copyFields(to.fields)\">" +
                        "      <formly-form fields=\"fields\" model=\"element\" form=\"form\"></formly-form>" +
                        "      <div style=\"margin-bottom:20px;\">" +
                        "        <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"model[options.key].splice($index, 1)\">" +
                        "          Remove" +
                        "        </button>" +
                        "      </div>" +
                        "      <hr>" +
                        "  </div>" +
                        "  <p class=\"AddNewButton\">" +
                        "    <button type=\"button\" class=\"btn btn-primary\" ng-click=\"addNew()\" >Add</button>" +
                        "  </p>" +
                        "</div>" +
                        "</script>";

                    //var myEl = angular.element(document.querySelector('body'));
                    //myEl.prepend(template);

                    $(template).insertBefore("script");
                    //$('body').append(template);
                }
            }

            /* checks if all array elements are not undefined. if one is undefined return false */
            function CheckArrayValues(array) {
                var goOn = true;

                angular.forEach(array, function (value, key) {
                    if (value === undefined) {
                        goOn = false;
                        return goOn;
                    }
                });

                return goOn;
            }
        }
    );

}());

